﻿using System;
using System.Xml;
using ThatsMeSDK.Core.Filter;
using ThatsMeSDK.Exceptions;

namespace ThatsMeSDK.Core
{
	/// <summary>
	/// KernelFunc holds working functions for the Kernel
	/// </summary>
	internal static class ServiceFunctions
	{
		private static HtmlFilter filter = new HtmlFilter();
		
		/// <summary>
		/// Fills member data into a member object
		/// </summary>
		/// <param name="memberData">XmlNode which contains the member data</param>
		/// <returns>Filled Member Object</returns>
		internal static Member FillMemberData(XmlNode memberData)
		{
			Member tempMember = new Member();
			
			//Fill Member Attributes
			tempMember.Id = Convert.ToInt32(memberData.SelectSingleNode("id").InnerText);
			tempMember.Nick = memberData.SelectSingleNode("nick").InnerText;
			tempMember.Birthday = DateTime.Parse(memberData.SelectSingleNode("birthday").InnerText);
			tempMember.Sex = (Gender)Enum.Parse(typeof(Gender), memberData.SelectSingleNode("sex").InnerText);
			tempMember.ProfilePictureUri = new Uri(memberData.SelectSingleNode("image").InnerText);
			tempMember.ProfileUri = new Uri(memberData.SelectSingleNode("profile").InnerText);
			tempMember.Description = filter.Filter(memberData.SelectSingleNode("profiletext").FirstChild.Value);
			
			//Canton Emtpy Bug
			if (memberData.SelectSingleNode("canton").InnerText == string.Empty || memberData.SelectSingleNode("canton").InnerText == "--")
			{
				tempMember.Canton = Canton.CantonShortName.Empty;
			}
			else
			{
				tempMember.Canton = (Canton.CantonShortName)Enum.Parse(typeof(Canton.CantonShortName), memberData.SelectSingleNode("canton").InnerText);
			}
			
			return tempMember;
		}
		
		/// <summary>
		/// Checks if the returned data has been authentificated correctly
		/// </summary>
		/// <param name="returnData">return data to check</param>
		/// <returns>Boolean</returns>
		internal static bool CheckAuthentificationError(XmlDocument returnData)
		{
			if (returnData.SelectSingleNode("error") == null)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		
		/// <summary>
		/// Fills message data into a message object
		/// </summary>
		/// <param name="message">XmlNode which contains the message data</param>
		/// <returns>Filled message object</returns>
		internal static Message FillMessageData(XmlNode messageData)
		{
			XmlNode sourceNode = messageData.SelectSingleNode("source");
			Message tempMessage = new Message();
			
			tempMessage.Header = FillMessageHeaderData(messageData);
			tempMessage.Body = filter.Filter(messageData.SelectSingleNode("body").FirstChild.Value); //CDATA
			tempMessage.IsNotification = IntToBool(Convert.ToInt32(messageData.SelectSingleNode("notification").InnerText));
			tempMessage.IsSentFromMobile = IntToBool(Convert.ToInt32(messageData.SelectSingleNode("sentfrommobile").InnerText));
			
			if (sourceNode != null)
			{
				tempMessage.Source = new Message.SourceMessage(
					IntToBool(Convert.ToInt32(sourceNode.SelectSingleNode("forumpost").InnerText)),
					sourceNode.SelectSingleNode("body").FirstChild.Value); //CDATA
			}
			
			return tempMessage;
		}
		
		/// <summary>
		/// Fills message header data into a message header object
		/// </summary>
		/// <param name="message">XmlNode which contains the message header data</param>
		/// <returns>Filled message header object</returns>
		internal static MessageHeader FillMessageHeaderData(XmlNode messageheaderData)
		{
			XmlNode fromNode = messageheaderData.SelectSingleNode("from");
			XmlNode toNode = messageheaderData.SelectSingleNode("to");
			MessageHeader tempHeader = new MessageHeader();
			
			tempHeader.Id = Convert.ToInt32(messageheaderData.SelectSingleNode("id").InnerText);
			tempHeader.Subject = messageheaderData.SelectSingleNode("subject").FirstChild.Value; //CDATA
			tempHeader.IsRead = IntToBool(Convert.ToInt32(messageheaderData.SelectSingleNode("read").InnerText));
			tempHeader.IsReplied = IntToBool(Convert.ToInt32(messageheaderData.SelectSingleNode("replied").InnerText));
			tempHeader.SendDate = DateTime.Parse(messageheaderData.SelectSingleNode("senddate").InnerText);
			
			tempHeader.From = new MessageHeader.MessageContact(
				Convert.ToInt32(fromNode.SelectSingleNode("id").InnerText),
				fromNode.SelectSingleNode("nick").InnerText);
			
			tempHeader.To = new MessageHeader.MessageContact(
				Convert.ToInt32(toNode.SelectSingleNode("id").InnerText),
				toNode.SelectSingleNode("nick").InnerText);
			
			return tempHeader;
		}
		
		/// <summary>
		/// Fills picturedata into a picture object
		/// </summary>
		/// <param name="picture">XmlNode of the picturedata</param>
		/// <returns>Filled GalleryPicture Object</returns>
		internal static GalleryPicture FillGalleryPictureData(XmlNode pictureData)
		{
			XmlNode votesNode = pictureData.SelectSingleNode("votes");
			XmlNode srcNode = pictureData.SelectSingleNode("src");
			XmlNode memberNode = pictureData.SelectSingleNode("member");
			GalleryPicture tempPicture = new GalleryPicture();
			
			tempPicture.Id = Convert.ToInt32(pictureData.SelectSingleNode("id").InnerText);
			tempPicture.Url = new Uri(pictureData.SelectSingleNode("url").InnerText);
			tempPicture.Added = DateTime.Parse(pictureData.SelectSingleNode("added").InnerText);
			tempPicture.CommentsCount = Convert.ToInt32(pictureData.SelectSingleNode("commentsCount").InnerText);
			tempPicture.FavsCount = Convert.ToInt32(pictureData.SelectSingleNode("favsCount").InnerText);
			tempPicture.Views = Convert.ToInt32(pictureData.SelectSingleNode("views").InnerText);
			
			tempPicture.PositiveVotes = Convert.ToInt32(votesNode.SelectSingleNode("positive").InnerText);
			tempPicture.NegativeVotes = Convert.ToInt32(votesNode.SelectSingleNode("negative").InnerText);
			
			tempPicture.SourceBig = new Uri(srcNode.SelectSingleNode("big").InnerText);
			tempPicture.SourceThumb = new Uri(srcNode.SelectSingleNode("thumb").InnerText);
			tempPicture.SourceMini = new Uri(srcNode.SelectSingleNode("mini").InnerText);
			
			tempPicture.MemberId = Convert.ToInt32(memberNode.SelectSingleNode("id").InnerText);
			tempPicture.MemberNick = memberNode.SelectSingleNode("nick").InnerText;
			tempPicture.MemberProfilePage = new Uri(memberNode.SelectSingleNode("profile").InnerText);
			
			return tempPicture;
		}
		
		/// <summary>
		/// Fills categoryData into a GalleryCategory object
		/// </summary>
		/// <param name="picture">XmlNode of the categoryData</param>
		/// <returns>Filled GalleryCategory Object</returns>
		internal static GalleryCategory FilleGalleryCategoryData(string nick, XmlNode categoryData)
		{
			GalleryCategory tempCategory = new GalleryCategory(nick);
			
			tempCategory.Id = Convert.ToInt32(categoryData.SelectSingleNode("id").InnerText);
			tempCategory.Title = categoryData.SelectSingleNode("title").FirstChild.Value; //CDATA
			tempCategory.Description = categoryData.SelectSingleNode("description").FirstChild.Value; //CDATA
			tempCategory.PicsCount = Convert.ToInt32(categoryData.SelectSingleNode("picsCount").InnerText);
			
			return tempCategory;
		}
		
		/// <summary>
		/// Converts 0 or 1 to boolean false or true
		/// </summary>
		/// <param name="value">0 or 1 integer</param>
		/// <returns>boolean</returns>
		public static bool IntToBool(int value)
		{
			if(value == 0)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		
		/// <summary>
		/// Checks if the ServiceHandler is Ready to do something
		/// </summary>
		/// <returns>Returns 0 if everything is ok</returns>
		internal static void CheckServiceHandlerReadyState()
		{
			if (ServiceHandler.dataloader == null)
			{
				//Set Default Value
				ServiceHandler.Initialize(DataFormat.Xml);
				
				//throw new Exception("ServiceHandler is not initialized!");
			}
		}
		
		/// <summary>
		/// Checks if the request has returned an error
		/// </summary>
		/// <param name="data">Loaded XmlDocument</param>
		/// <returns>Same Xml Document as input</returns>
		internal static XmlDocument CheckData(XmlDocument data)
		{
			//Check if it has an error Node
			XmlNode errorNode = data.SelectSingleNode("error");
			
			if (errorNode != null)
			{
				XmlNode idNode = errorNode.SelectSingleNode("id");
				XmlNode textNode = errorNode.SelectSingleNode("text");
				
				//Create exception
				if (idNode != null && textNode != null)
				{
					ApiException ex = new ApiException(Convert.ToInt32(idNode.InnerText), textNode.InnerText, data);
					
					//throw exception
					throw ex;
				}
			}
			
			return data;
		}
	}
}
